#include "GlVertexBuffer.h"

namespace gname
{
	GLVertexBuffer::GLVertexBuffer(int size,int typeDataSize,unsigned usage)
	{
		
		vertexStreamData = 0;
		
		isInit = false;
	    
		vboUsage  =  usage;

		vboId     = 0;

		Locked = false;
		
		typeSize = typeDataSize;
		
		Alloc(size);
		
		next = size;
		for(int i = 0; i <8 ; i++)
		{
			texData[i] = 0;
		}
	
		if(!isExtensionSupported("GL_ARB_vertex_buffer_object"))
	    {
		
	      // throw std::exception::exception( "Cant create VBO Array without extension GL_ARB_vertex_buffer_object");
		}

		
	}

	void GLVertexBuffer::Init()
	{     
		
		
		GenVbo();
		
		glBindBufferARB(GL_ARRAY_BUFFER, vboId);
		
		glBufferDataARB(GL_ARRAY_BUFFER, vertexCount * typeSize, vertexStreamData, vboUsage);
		

		//ApplyVertexAttribs();
		
		isInit = true;
	}

	/*void  GLVertexBuffer::ApplyVertexAttribs()
	{
		
		
	}*/

	unsigned GLVertexBuffer::GetId() const
	{
	return vboId;
	}
	
	void GLVertexBuffer::AddData(void *data, int newSize)
	{
		isInit = false;
		
		//void *dat = data;
		if(next >= vertexCount)
		{
		  IncreaseMemory(newSize);
		}
		vertexStreamData[next++] = data;
		Init();
	}

	bool GLVertexBuffer::IsLock()
	{
		return Locked;
	}
	void GLVertexBuffer::IncreaseMemory(int newSize)
	{
		isInit = false;
		//const int psz = sizeof(void*);
		void**temp = new void*[(vertexCount+newSize)*typeSize];
		memset(temp ,0,(vertexCount+newSize)*typeSize);
		memcpy(temp,vertexStreamData,typeSize * (vertexCount));
		vertexCount+=newSize;
		Clear();
		vertexStreamData = temp;
	}
	
	bool GLVertexBuffer::IsOk()
	{
		if(isInit)
			return true;
		
		return false;
	}
	
	void GLVertexBuffer::Alloc(int verCount )
	{
		isInit = false;
		
		if(vertexStreamData!=0)
		{
			Clear();

		  
		}
		

		 if(verCount!=0)
		   {
			vertexCount = verCount;
			vertexStreamData = new void*[verCount*typeSize];
		   }

	}
	void GLVertexBuffer::Resize(int newVertexSize)
	{
		vertexCount = newVertexSize;
		
		
		void**tempVert = 0;
		

		try
		{   
			tempVert = new void*[vertexCount*typeSize];
			

		}
		catch(...)
		{
			// std::exception::exception( "Out of memory");
			 vertexCount = 0;
		}

		memcpy ( tempVert, vertexStreamData, typeSize * vertexCount );
		

		

		Clear();
		vertexStreamData = tempVert;
		
		Init();
}
	

	 
	 
	

	   
	   void GLVertexBuffer::SetData( void* vert) 
	   {
		   memcpy(vertexStreamData,vert,vertexCount*typeSize);
	   }
	  
	

void GLVertexBuffer::Clear()
	{
		glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
	    DeleteVbo();

		if(vertexStreamData!=0)
        delete [] vertexStreamData; 
	}
	
     
int GLVertexBuffer::GetCountOfVbo() const
{
		GLint size;
	    glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size);
	    return	(unsigned) size;
}
void GLVertexBuffer::GenVbo()
{
	if(vboId == 0)
	{
		glGenBuffersARB(1, &vboId);
		
	}
}
	
void GLVertexBuffer:: DeleteVbo()
{
	if(vboId!=0)
	{
		glBindBufferARB(GL_ARRAY_BUFFER, 0);
		glDeleteBuffersARB(1, &vboId);
		
		vboId  = 0;
	}
}

	

	
void GLVertexBuffer::Lock()
{
	if (Locked) 
		return;

	glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboId);
	
	*vertexStreamData = (glMapBufferARB(GL_ARRAY_BUFFER_ARB, vboUsage));

	if(!vertexStreamData)
	{
		int id = glGetError();
		
	}

	glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);

	

	Locked = true;
}


	
void GLVertexBuffer::Unlock()
{
	glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboId);
	
	if (!Locked) 
		return;

	if(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)==GL_FALSE)
	{
		
	}
		
	

	Locked = false;
}


GLVertexBuffer::~GLVertexBuffer()
{
	Clear();
	
}
};